package com.hb.trade.api.routine.controller.center.au;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.hb.core.pojo.center.au.entity.ApiInfo;
import com.hb.core.pojo.parent.PageResult;
import com.hb.trade.api.routine.config.pay.WeixinPayBody;
import com.hb.trade.client.center.ApiInfoRoleClient;
import lombok.extern.slf4j.Slf4j;
import org.fzzn.core.model.msg.LayuiResponseDto;
import org.fzzn.core.model.msg.Message;
import org.fzzn.core.model.msg.ResponseDto;
import org.fzzn.core.util.ResultUtil;
import org.fzzn.core.web.anno.Version;
import org.springframework.context.ApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;

/**
 * 接口管理
 *
 * @author zhaojk
 */
@Slf4j
@Version(1.0)
@RequestMapping("/{version}")
@RestController
public class ApiInfoController {

    protected final ApiInfoRoleClient apiInfoRoleClient;

    public ApiInfoController(ApiInfoRoleClient apiInfoRoleClient) {
        this.apiInfoRoleClient = apiInfoRoleClient;
    }
    /**
     * 扫描项目中的所有接口
     *
     * @return
     */
    @RequestMapping("/test/apiInfo/pageInterfaces")
    public LayuiResponseDto pageInterfaces(@RequestBody ApiInfo apiInfo) {
        Message<PageResult<ApiInfo>> pageMsg = apiInfoRoleClient.pageApiInfos(apiInfo);
        if (pageMsg.isSuccess()) {
            PageResult<ApiInfo> data = pageMsg.getData();
            return ResultUtil.layData(0, "", data.getTotal(), data.getRecords());
        }
        return ResultUtil.layData(0, "", 0, null);
    }

    /**
     * 扫描项目中的所有接口
     *
     * @return
     */
    @RequestMapping("/test/refresh/interfaces")
    public ResponseDto<?> refreshInterfaces() {
        ApplicationContext applicationContext = SpringUtil.getApplicationContext();
        List<ApiInfo> root = CollUtil.list(false);

        String[] controllerNames = applicationContext.getBeanNamesForAnnotation(RestController.class);
        int count = 0;
        for (String controllerName : controllerNames) {
            Object bean = SpringUtil.getBean(controllerName);
            Method[] methods = ReflectUtil.getMethods(bean.getClass(), (method) -> method.getAnnotation(GetMapping.class) != null
                    || method.getAnnotation(PostMapping.class) != null
                    || method.getAnnotation(RequestMapping.class) != null);

            for (Method method : methods) {
                ApiInfo apiInfo = new ApiInfo();
                apiInfo.setControlName(controllerName);

                Annotation[][] parameterAnnotations = method.getParameterAnnotations();
                for (Annotation[] parameterAnnotation : parameterAnnotations) {
                    for (Annotation annotation : parameterAnnotation) {
                        Parameter[] parameters = method.getParameters();
                        if (annotation instanceof RequestBody) {
                            apiInfo.setParamType(MediaType.APPLICATION_JSON_VALUE);

                            Parameter parameter = parameters[0];
                            Type parameterizedType = parameter.getParameterizedType();
                            Object ifPossible;
                            try {
                                ifPossible = ReflectUtil.newInstance(parameterizedType.getTypeName());
                                if (ifPossible instanceof String) {
                                    System.out.println(ifPossible);
                                    apiInfo.setParamExample(String.valueOf(ifPossible));
                                } else {
                                    apiInfo.setParamExample(JSONUtil.parseObj(ifPossible, false).toJSONString(2));
                                }
                            } catch (UtilException e) {
                                apiInfo.setParamExample(e.getMessage());
                            }
                        } else {
                            apiInfo.setParamType(MediaType.APPLICATION_FORM_URLENCODED_VALUE);
                            apiInfo.setParamExample(ArrayUtil.toString(parameters));
                        }

                    }
                }

                String[] values;

                GetMapping getAnno = method.getAnnotation(GetMapping.class);
                if (getAnno != null) {
                    values = getAnno.value();
                    if (ArrayUtil.isNotEmpty(values)) {
                        apiInfo.setApiName(values[0]);
                        apiInfo.setReqType("GET");
                    }
                }

                PostMapping postAnno = method.getAnnotation(PostMapping.class);
                if (postAnno != null) {
                    values = postAnno.value();
                    if (ArrayUtil.isNotEmpty(values)) {
                        apiInfo.setApiName(values[0]);
                        apiInfo.setReqType("POST");
                    }
                }

                RequestMapping requestAnno = method.getAnnotation(RequestMapping.class);
                if (requestAnno != null) {
                    values = requestAnno.value();
                    if (ArrayUtil.isNotEmpty(values)) {
                        apiInfo.setApiName(values[0]);
                        apiInfo.setReqType("REQUEST");
                    }
                }
                count++;
                if (apiInfo.getParamExample() == null) {
                    apiInfo.setParamExample(StrUtil.EMPTY);
                }
                root.add(apiInfo);
            }
        }
        System.out.println("接口总数: " + count);
        Message<Boolean> booleanMessage = apiInfoRoleClient.updateApis(root);
        return ResultUtil.msg(booleanMessage);
    }
}
